/*
 *
 *  * Copyright 2018-present KunMinX
 *  *
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *    http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *
 */

package com.kunminx.architecture.ui.page;

import android.annotation.SuppressLint;
import android.content.pm.ApplicationInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

import com.kunminx.strictdatabinding.R;


/**
 * Create by KunMinX at 19/8/1
 */
public abstract class DataBindingActivity extends AppCompatActivity {

  private ViewDataBinding mBinding;
  private TextView mTvStrictModeTip;

  protected abstract void initViewModel();

  protected abstract DataBindingConfig getDataBindingConfig();

  /**
   * TODO tip: 警惕使用。非必要情况下，尽可能不在子类中拿到 binding 实例乃至获取 view 实例。使用即埋下隐患。
   * 目前方案是于 debug 模式，对获取实例情况给予提示。
   * <p>
   * 如这么说无体会，详见 https://xiaozhuanlan.com/topic/9816742350 和 https://xiaozhuanlan.com/topic/2356748910
   *
   * @return binding
   */
  protected ViewDataBinding getBinding() {
    if (isDebug() && mBinding != null) {
      if (mTvStrictModeTip == null) {
        mTvStrictModeTip = new TextView(getApplicationContext());
        mTvStrictModeTip.setAlpha(0.4f);
        mTvStrictModeTip.setPadding(
                mTvStrictModeTip.getPaddingLeft() + 24,
                mTvStrictModeTip.getPaddingTop() + 64,
                mTvStrictModeTip.getPaddingRight() + 24,
                mTvStrictModeTip.getPaddingBottom() + 24);
        mTvStrictModeTip.setGravity(Gravity.CENTER_HORIZONTAL);
        mTvStrictModeTip.setTextSize(10);
        mTvStrictModeTip.setBackgroundColor(Color.WHITE);
        @SuppressLint({"StringFormatInvalid", "LocalSuppress"})
        String tip = getString(R.string.debug_databinding_warning, getClass().getSimpleName());
        mTvStrictModeTip.setText(tip);
        ((ViewGroup) mBinding.getRoot()).addView(mTvStrictModeTip);
      }
    }
    return mBinding;
  }

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    initViewModel();
    DataBindingConfig dataBindingConfig = getDataBindingConfig();

    //TODO tip: DataBinding 严格模式：
    // 将 DataBinding 实例限制于 base 页面中，默认不向子类暴露，
    // 通过这方式，彻底解决 视图调用一致性问题，
    // 如此，视图调用安全性将与基于函数式编程思想 Jetpack Compose 持平。

    // 如这么说无体会，详见 https://xiaozhuanlan.com/topic/9816742350 和 https://xiaozhuanlan.com/topic/2356748910

    ViewDataBinding binding = DataBindingUtil.setContentView(this, dataBindingConfig.getLayout());
    binding.setLifecycleOwner(this);
    binding.setVariable(dataBindingConfig.getVmVariableId(), dataBindingConfig.getStateViewModel());
    SparseArray<Object> bindingParams = dataBindingConfig.getBindingParams();
    for (int i = 0, length = bindingParams.size(); i < length; i++) {
      binding.setVariable(bindingParams.keyAt(i), bindingParams.valueAt(i));
    }
    mBinding = binding;
  }

  public boolean isDebug() {
    return getApplicationContext().getApplicationInfo() != null &&
            (getApplicationContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mBinding.unbind();
    mBinding = null;
  }
}
